﻿using System;
using System.IO;
using System.Collections.Generic;

namespace Game.Lib.CSG
{
    public class LineSegment : Shape1D
    {
        public override List<Vector> CriticalPoints
        {
            get
            {
                List<Vector> ret = new List<Vector>(3);
                ret.Add(Start);
                ret.Add(MidPoint);
                ret.Add(End);
                return ret;
            }
        }
        public Vector2 Start
        {
            get
            {
                return _Start;
            }
            set
            {
                if (value.X > _End.X)
                {
                    _Start = _End;
                    _End = value;
                }
                else _Start = value;
            }
        }

        public Vector2 End
        {
            get
            {
                return _End;
            }
            set
            {
                if (value.X < _Start.X)
                {
                    _End = _Start;
                    _Start = value;
                }
                else _End = value;
            }
        }

        public override float Length
        {
            get { return Vector2.Distance(Start, End); }
        }

        public float Slope
        {
            get
            {
                return (End.Y - Start.Y) / (End.X - Start.X);
            }
        }

        public Vector2 MidPoint
        {
            get
            {
                return Start + (End - Start) * .5f;
            }
        }

        public Line BoundingLine
        {
            get
            {
                return new Line(Start, Slope);
            }
        }

        private Vector2 _Start;
        private Vector2 _End;

        public LineSegment()
        {
            Start = End = Vector2.Zero;
        }

        public LineSegment(Vector2 p0, Vector2 p1)
        {
            Start = p0;
            End = p1;
        }

        public LineSegment(Vector2 point, float slope, float length)
        {
            Start = point;
            double theta = Math.Atan(slope);
            End = Start + Vector2.FromPolar(length, (float)theta);
        }

        public LineSegment(Line a, float t0, float t1)
        {
            Start = a.Get(t0);
            End = a.Get(t1);
        }

        public static Vector2 Intersection(LineSegment a, LineSegment b)
        {
            Vector2 test = Line.Intersection(a.BoundingLine, b.BoundingLine);
            if (a.Contains(test) && b.Contains(test)) return test;
            return null;
        }

        public bool Contains(Vector2 a)
        {
            if(a.X < Start.X || a.X > End.X ) return false;
            return a.Y-Start.Y - Slope * (a.X - Start.X) < Utils.Epsilon;
        }


        public override void Serialize(Stream s)
        {
            Start.Serialize(s);
            End.Serialize(s);
        }

        public override void Deserialize(Stream s)
        {
            Start.Deserialize(s);
            End.Deserialize(s);
        }
    }
}
